﻿#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>

//字符指针变量
//int main()
//{
//	//一般使用情况
//	//char ch = 'w';
//	//char* p = &ch;
//	//另一种使用情况
//	char arr[] = "abcdfe";
//	char* p = arr;
//	/*printf("%d ", *p);*///结果是97,打印首元素a的地址
//	printf("%c ", *p);//结果是a
//	//是把一个常量字符串的首字符 a 的地址存放到指针变量 p 中
//
//	return 0;
//}


//数组指针变量
//int main()
//{
//	int arr[10] = {0};
//    int (* p)[10] = &arr;//数组的地址，p 是数组指针变量
//    //parr 就是数组指针变量
//
//	return 0;
//}
//注：[]的优先级要高于*号的，所以必须加上（）来保证p先和*结合。

//数组指针变量初始化
//int main()
//{
//	int arr[10] = { 0 };
//	int (*p)[10]= &arr;
////   int                      (*p)                  [10]= &arr;
////   |                         |                     |
//// p指向的数组的元素类型      p是数组指针的变量名    p指向数组的元素个数
////
//	return 0;
//}


//二维数组传参的本质
//旧方法：
//void test(int arr[3][5], int r, int c)//行：row;列：column
//{
//	int i = 0;
//	int j = 0;
//	for (i = 0; i < r; i++)
//	{
//		for (j = 0; j < c; j++)
//		{
//			printf("%d ", arr[i][j]);
//		}
//		printf("\n");
//	}
//}
//
//int main()
//{
//	int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
//	test(arr, 3, 5);
//	return 0;
//}

//新方法：
//void test(int (*p)[5], int r, int c)//行：row;列：column
//{
//	int i = 0;
//	int j = 0;
//	for (i = 0; i < r; i++)
//	{
//		for (j = 0; j < c; j++)
//		{
//			printf("%d ", *(*(p+i)+j));
//		}
//		printf("\n");
//	}
//}
//
//int main()
//{
//	int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
//	test(arr, 3, 5);
//	return 0;
//}


//函数指针变量
//函数指针变量应该是用来存放函数地址的，未来通过地址能够调用函数的。

//int Add(int x, int y)
//{
//	return x + y;
//}
//
//int main()
//{
//	int ret = 0;
//   // ret = Add(20, 30);
//	int (*pf)(int , int ) = &Add;//参数名可写也可不写，但是参数类型必写
//	ret = (*pf)(2, 3);
//	//ret = pf(2, 3);
//	//(*pf)(2,3)=pf(2,3)
//	printf("%d\n", ret);
//	printf("%p\n", &Add);
//	printf("%p\n", Add);
//	//&函数名 和 函数名 拿到的都是函数的地址
//	//函数名就是函数的地址，当然也可以通过& 函数名 的方式获得函数的地址。
//	return 0;
//}

//  int                           (*pf)            (int x,int y)
//   |                              |                    |
// pf指向函数的返回类型           函数指针变量名    pf指向函数的参数类型和个数的交代
// int (*) (int x, int y) //pf函数指针变量的类型
// 


//两段有趣的代码
// 
//1.(* (void ( * )( ) ) 0 ) ( );
//对这串代码的解释：
//int main()
//{
//	(*(void(*)())0) ();
//	return 0;
//}
// 
//void ( * )( )-->是函数指针类型
//把0强制类型转换成void ( * )( )这种类型的函数指针
// 而0现在是一个函数的地址，这个函数无参数，返回类型是void
// 
//return 0;是用来调用0地址处的函数
//
// 2.void ( * signal( int, void(*)(int) ) )(int);
// 对这串代码的解释：
// signal(int,void(*)(int))
// signal是一个函数的名字
// signal(int,void(*)(int))这句代码是一个函数的声明
//声明的这个函数的名字是signal
//signal函数有2个参数，第一个参数是int类型的，第二个参数是void(*)(int)这样的函数指针类型，该函数指针
// 能够指向的函数参数是int类型，返回类型是void
// signal函数的返回类型也是void(*)(int)这样的函数指针类型,该函数指针能够指向的函数参数是int类型
// 
//由于第二串代码比较复杂，我们可以引用typedef关键字，来对第二串代码进行简化
//typedef unsigned int uint;
//
//typedef int* ptr_t;
//
//typedef int(*parr_t)[10];//parr_t 是数组指针类型


//函数指针数组
//
// 前面已学过
// 字符指针变量、整型指针变量、数组指针变量、函数指针变量
// 
//是 int (*)() 类型的函数指针。

//int Add(int x, int y)
//{
//	return x + y;
//}
//
//int Sub(int x, int y)
//{
//	return x - y;
//}
//
//int main()
//{
//	int (*pf1)(int, int) = Add;
//	int (*pf2)(int, int) = Sub;
//	int ret1 = Add(2, 3);
//	int ret2 = Sub(6, 5);
//	int (*pfArr[4])(int, int) = { Add,Sub };
//	//Add, Sub这些函数的地址存放在一个数组中
//	//函数指针数组 - 存放函数指针的数组
//	printf("%p ", (*pfArr));
//	printf("%d %d\n", ret1, ret2);
//	return 0;
//}


//函数指针数组的使用
//写一个计算器
//完成整数的：加法、减法、乘法、除法

//旧方法：
//void menu()
//{
//	printf("*************************\n");
//	printf("**** 1.Add     2.Sub ****\n");
//	printf("**** 3.Mul     4.Div****\n");
//	printf("****      0.exit    *****\n");
//	printf("*************************\n");
//
//}
//
//int Add(int x, int y)
//{
//	return x + y;
//}
//
//int Sub(int x, int y)
//{
//	return x - y;
//}
//
//int Mul(int x, int y)
//{
//	return x * y;
//}
//
//int Div(int x, int y)
//{
//	return x / y;
//}
//
//int main()
//{
//	int x = 0;
//	int y = 0;
//	int ret = 0;
//	int input = 0;
//	do
//	{
//		menu();
//		printf("请选择:>");
//		scanf("%d", &input);
//		switch (input)
//		{
//		case 1:
//			printf("请输入两个操作数>:");
//			scanf("%d %d", &x, &y);
//			ret = Add(x, y);
//			printf("%d\n", ret);
//			break;
//		case 2:
//			printf("请输入两个操作数>:");
//			scanf("%d %d", &x, &y);
//			ret = Sub(x, y);
//			printf("%d\n", ret);
//			break;
//		case 3:
//			printf("请输入两个操作数>:");
//			scanf("%d %d", &x, &y);
//			ret = Mul(x, y);
//			printf("%d\n", ret);
//			break;
//		case 4:
//			printf("请输入两个操作数>:");
//			scanf("%d %d", &x, &y);
//			ret = Div(x, y);
//			printf("%d\n", ret);
//			break;
//		case 0:
//			printf("退出计算器\n");
//			break;
//		default:
//			printf("选择错误，请重新选择\n");
//			break;
//
//		}
//	} while (input);
//
//	return 0;
//}


//新方法一：
//void menu()
//{
//	printf("*************************\n");
//	printf("**** 1.Add     2.Sub ****\n");
//	printf("**** 3.Mul     4.Div****\n");
//	printf("****      0.exit    *****\n");
//	printf("*************************\n");
//
//}
//
//int Add(int x, int y)
//{
//	return x + y;
//}
//
//int Sub(int x, int y)
//{
//	return x - y;
//}
//
//int Mul(int x, int y)
//{
//	return x * y;
//}
//
//int Div(int x, int y)
//{
//	return x / y;
//}
//
//int main()
//{
//	int x = 0;
//	int y = 0;
//	int ret = 0;
//	int input = 0;
//	//函数指针数组 - 转移表
//	int (*pfArr[5])(int, int) = { 0,Add,Sub,Mul,Div };
//	//                            0, 1,  2,  3,  4
//	do
//	{
//		menu();
//		printf("请选择:>");
//		scanf("%d", &input);
//		if(input>=1&&input<=4)
//		{
//			printf("请输入两个操作数\n");
//			scanf("%d %d", &x, &y);
//			ret = pfArr[input](x, y);
//			printf("%d\n", ret);
//		}
//		else if (input == 0)
//		{
//			printf("退出计算器\n");
//			break;
//		}
//		else
//		{
//			printf("选择错误，重新选择\n");
//		}
//	} while (input);
//
//	return 0;
//}


//新方法二：
//void menu()
//{
//	printf("*************************\n");
//	printf("**** 1.Add     2.Sub ****\n");
//	printf("**** 3.Mul     4.Div****\n");
//	printf("****      0.exit    *****\n");
//	printf("*************************\n");
//
//}
//
//int Add(int x, int y)
//{
//	return x + y;
//}
//
//int Sub(int x, int y)
//{
//	return x - y;
//}
//
//int Mul(int x, int y)
//{
//	return x * y;
//}
//
//int Div(int x, int y)
//{
//	return x / y;
//}
//
//void Calc(int (*pf)(int, int))
//{
//	int x = 0; 
//	int y = 0;
//	int ret = 0;
//	printf("请输入两个操作数>;");
//	scanf("%d %d", &x, &y);
//	ret = pf(x, y);
//	printf("%d\n", ret);
//}
//
//int main()
//{
//    int input = 0;
//	do
//	{
//		menu();
//		printf("请选择:>");
//		scanf("%d", &input);
//		switch (input)
//		{
//		case 1:
//			Calc(Add);
//			break;
//		case 2:
//			Calc(Sub);
//			break;
//		case 3:
//			Calc(Mul);
//			break;
//		case 4:
//			Calc(Div);
//			break;
//		case 0:
//			printf("退出计算器\n");
//			break;
//		default:
//			printf("选择错误，请重新选择\n");
//			break;
//
//		}
//	} while (input);
//
//	return 0;
//}


//sizeof和strlen的对比
//sizeof:
//1. sizeof是操作符; 2. sizeof计算操作数所占内存的大小，单位是字节; 3. 不关注内存中存放什么数据
//strlen:
//1. strlen是库函数，使用需要包含头文件 string.h 
//2. srtlen是求字符串长度的，统计的是 \0 之前字符的个数
//3. 关注内存中是否有 \0 ，如果没有 \0 ，就会持续往后找，可能会越界


//%c是打印单字符；%s是打印字符串
//字符函数和字符串函数
#include <ctype.h>
//1.字符分类函数
//这些函数的使用都需要包含一个头文件是 ctype.h
//举例，对islower和isdigit的使用

//islower 函数用于检查给定的字符是否为小写字母（即 'a' 到 'z'）
// 如果参数是小写字母,返回值是一个整数（尽管具体的非零值可能是实现定义的，但通常是 1）;如果参数是大写字母，返回一个0
// 所以打印结果为2而不是1
// 因为这实际上是一个特定于实现的行为，因为标准只要求 islower 在字符是小写字母时返回非零值，而没有规定必须返回 1。
//int main()
//{
//	int ret = islower('x');
//	printf("%d\n", ret);
//	if (ret)
//		printf("大写\n");
//	else
//		printf("小写\n");
//	return 0;
//}


//isdigit 函数用于检查给定的字符是否为十进制数字字符（即 '0' 到 '9'）
// 如果参数是 '0' 到 '9' 之间的字符,返回值是一个整数；反则，会返回0
// 所以打印结果是0，因为X 不是 '0' 到 '9' 之间的字符，则返回0
//int main()
//{
//	int ret = isdigit('X');//'0'~'9'
//	printf("%d\n", ret);
//
//	return 0;
//}


//写一个代码，将字符串中的小写字母转大写，其他字符不变。
//int main()
//{
//	char arr[30] = "hi,i am a girl";
//	int i = 0;
//	while (arr[i])
//	{
//		if (islower(arr[i]))//核心思想
//		{
//			arr[i] = arr[i] - 32;
//
//		}
//		i++;
//	}
//	printf("%s\n", arr);
//	return 0;
//}


//2.字符转换函数
//int tolower(int c); //将参数传进去的大写字母转小写 
//int toupper(int c); //将参数传进去的小写字母转大写
//
//上面的代码可以改成下面的形式：
//int main()
//{
//	char arr[30] = "hi,i am a girl";
//	int i = 0;
//	while (arr[i])
//	{
//		if (islower(arr[i]))//核心思想
//		{
//			//arr[i] = arr[i] - 32;
//			arr[i] = toupper(arr[i]);
//		}
//		i++;
//	}
//	printf("%s\n", arr);
//	return 0;
//}

//int main()
//{
//	printf("%c\n", tolower('A'));
//	printf("%c\n", toupper('a'));
//	return 0;
//}


//strlen的使用和模拟实现
//包含头文件 #include <string.h>
#include <string.h>

//int main()
//{
//	char arr[] = "abcdef";//字符串以 '\0' 作为结束标志
//	// a b c d e f \0    从a开始数一直到\0就结束，不包括\0      
//	//size_t len = strlen(arr);//注意函数的返回值为 size_t，是无符号的；打印结果为6
//	size_t len = strlen(arr+1);
//	//a b c d e f \0     arr是首元素，则+1就是第二个元素，所以从b开始数一直到\0就结束，不包括\0
//	//打印结果为5
//	printf("%zd\n", len);
//
//	return 0;
//}

//计数器方式,用函数的方法
#include <assert.h>
//size_t my_strlen(const char* str)
//{
//	size_t count = 0;
//	//写assert宏来确保str不是空值，防止程序崩溃
//	assert(str != NULL);
//	while (* str)
//	{
//		count++;//在循环体内，每次循环都会使 count 的值增加 1，以计算字符串中的字符数
//		str++;//这行代码将 str 指针向前移动到字符串中的下一个字符。
//      //由于 str 是指向字符的指针，str++ 实际上是将指针的地址增加了一个 char 类型的大小（通常是 1 字节）
//	
//	}
//	return count;
//}

//指针-指针的方式
//size_t my_strlen(const char* str)
//{
//	size_t start = str;//令start的初始值为str的值，即字符串的起始地址
//	assert(str != NULL);
//	while (*str)
//	{
//		str++;
//	}
//	return str - start;
//	//str - start 是计算字符串起始位置到终止符‘\0’之前的字符串的长度
//}

//用函数递归方法
//size_t my_strlen(const char* str)
//{
//	if (*str == '\0')
//		return 0;
//	else
//		return 1 + my_strlen(str + 1);//每次递归返回时，都会将 1 加到之前的结果上，从而累积出整个字符串的长度。
//
//}
//
//int main()
//{
//	char arr[] = "abcdef";
//	size_t len = strlen(arr);
//	printf("%zd\n", len);//求字符串长度，不是打印字符串
//	return 0;
//}


//strcpy 的使用和模拟实现
//strcpy-->string copy-->字符串拷贝
//char* strcpy(char * destination, const char * source );
//                目标空间（arr2）             源头(arr1)
//把arr1中的字符串传到arr2中，就是相当于把arr1拷贝到arr2中

//int main()
//{
//	char arr1[] = "hello";
//	//char arr1[] = { 'a','b','c' };//错误的写法，没有'\0'，找不到字符的结束标志
//	char arr2[] = "xxxxxxxxxx";
//	strcpy(arr2, arr1);
//	//要注意一种错误想法：
//	//arr2!=arr1，这是因为数组名是地址，拷贝过去的是地址，而地址是常量的值，常量不可改变
//	//0x0012ff40 = 0x0012ff80，不可能相等
//	//3 = 5，不可能相等
//	printf("%s\n", arr2);
//	return 0;
//}

//错误示范
//int main()
//{
//	char arr1[] = "abcdefghi";//定义一个字符数组,这个数组在栈上分配内存，并且是可修改的。
//	char* p = "xxxxxxxxxxxxxxxxxxxxx";//常量字符串，
//	//定义一个字符指针，并让它指向一个字符串字面量"xxxxxxxxxxxxxxxxxxxxx"。字符串字面量通常存储在只读内存段（如.rodata段）中，因此是不可修改的。
//	strcpy(p, arr1);
//	//所以arr1的内容拷贝不到p中
//	printf("%s\n", p);
//	return 0;
//}


//strcpy的模拟实现:
//方式一
//char* my_strcpy(char* dest, char* src)
//{
//	//assert(dest != NULL);//方式一
//	//assert(src != NULL);
//	assert(dest && src);//方式二
//	while (*src != '\0')
//	{
//		*dest = *src;
//		src++;
//		dest++;
//	}
//	*dest = *src;
//  return dest;
//}

///方式二
//char* my_strcpy(char* dest, char* src)
//{
//	while (*src != '\0')
//	{
//		*dest++ = *src++;
//	}
//	*dest = *src;
//	return dest;
//}

//方式三
//char* my_strcpy(char* dest, const char* str)
//{
//	char* ret = dest;//保存 dest 的初始地址，以便在函数结束时返回。
//	assert(dest && str);
//	while(*dest++ = *str++)
//	{
//		;
//	}
//	return ret;
//}
//
//int main()
//{
//	char arr1[] = "abcdef";
//	char arr2[20] = "xxxxxxxxxxxx";
//	char* ret=my_strcpy(arr2, arr1);
//	printf("%s\n", ret-(int)(strlen(arr1)));
//	return 0;
//}


//strcat的使用和模拟实现
// strcat-->string concatenate-->字符串连接
//char* strcat(char * destination, const char * source );
//                目标空间(arr)                源头(world)
//int main()
//{
//	char arr[20] = "hello";
//	strcat(arr, "world");
//    //1. 找到目标空间中的第一个\0
//	//2. 然后从这个\0的位置开始追加源头字符串
//	//3. 源头字符串的内容，包括\0都会追加到目标空间
//
//	printf("%s\n", arr);
//	return 0;
//}

//char* my_strcat(char* dest, const char* src)
//{
//	char* ret = dest;
//	assert(dest && src);
//	while (*dest != '\0')//1.找到目标空间中的0
//	{
//		dest++;
//	}
//	while (*dest = *src)//2.拷贝数据
//	{
//		dest++;
//		src++;
//	}
//	return ret;
//}
//
//int main()
//{
//	char arr1[20] = "hello";
//	my_strcat(arr1, "world");
//	printf("%s\n", arr1);
//	return 0;
//}

//char* my_strcat(char* dest, const char* src)
//{
//	char* ret = dest;
//	assert(dest && src);
//	while (*dest != '\0')
//	{
//		dest++;
//	}
//	while (*src!='\0')
//	{
//		*dest = *src;
//		dest++;
//		src++;
//	}
//	*dest = '\0';
//	return ret;
//}
//
//int main()
//{
//	char arr1[30] = "hello";
//	//需要分配更大的空间来存储"hello"和"world"以及空字符，确保使用的时候有足够的空间
//	//所以不能写成char arr1[]="hello";  这样的形式会导致空间不够出现报错
//	char arr2[20] = "world";
//	char* r=my_strcat(arr1, arr2);
//	printf("%s\n", r);
//	return 0;
//}


//strcmp的使用和模拟实现
//int strcmp(const char* str1,const char* str2)
//                     str1 > str2 , 则返回大于0的数字   
//                     str1 = str2 , 则返回0的数字 
//                     str1 < str2 , 则返回小于0的数字 
//如：A组：abcd
//    B组：abd
//上面这两组比较，第一个元素都是a相等；第二个元素相等都是b；第三个元素A组是c,B组是d，而c<d,则B组大于A组

//int my_strcmp(char* str1, const char* str2)
//{
//	assert(str1 && str2);
//	while (*str1 == *str2)
//	{
//		if (*str1 == '\0')
//			return 0;
//		str1++;
//		str2++;
//	}
//	return *str1 - *str2;//返回两个不同字符的差值
//}
//
//int main()
//{
//	char arr1[] = "abcd";
//	char arr2[] = "abcq";
//	int ret=my_strcmp(arr1, arr2);
//	if (ret > 0)
//		printf(">\n");
//	else if (ret < 0)
//		printf("<\n");
//	else
//		printf("=\n");
//	return 0;
//}


//strncpy函数的使用,使用规则和strcpy一样
//1.拷贝num个字符从源字符串到目标空间。
//2.如果源字符串的长度小于num，则拷贝完源字符串之后，在目标的后边追加0，直到num个。
//
//int main()
//{
//	char arr1[] = "abcd";
//	char arr2[20] = "xxxxxxxxxx";
//	//strcpy(arr2, arr1);
//	strncpy(arr2, arr1, 5);
//	return 0;
//}


//strncat函数的使用
//1.将source指向字符串的前num个字符追加到destination指向的字符串末尾，再追加一个 \0 字符
//2.如果source指向的字符串的长度小于num的时候，只会将字符串中到\0 的内容追加到destination指向的字符串末尾。
//int main()
//{
//	char arr1[30] = "hjhshijianren";
//	char arr2[] = "baofu";
//	//strcat(arr1, arr2);
//	strncat(arr1, arr2, 13);
//	return 0;
//}


//strncmp函数的使用
//比较str1和str2的前num个字符，如果相等就继续往后比较，最多比较num个字母，
//如果提前发现不一样，就提前结束，大的字符所在的字符串大于另外一个。如果num个字符都相等，就是相等返回0.
//
//int main()
//{
//	char arr1[] = "abcdef";
//	char arr2[] = "abbbcdef";
//	int ret = strncmp(arr1, arr2, 3);
//	printf("%d\n", ret);
//	return 0;
//}
//两个数组比较，大于0就返回大于0的数，等于0就返回等于0的数，小于0就返回负数


//strstr的使用和模拟实现
//函数返回字符串str2在字符串str1中第一次出现的位置
//字符串的比较匹配不包含 \0 字符，以 \0 作为结束标志
//
// 解释：
// 匹配一次:
// arr1:a b c d e f a b c d e f  \0    //当arr2中'd'与arr1中'a'比较是不相等，则往后找；
//                                     当arr2中'd'与arr1中'b'比较是不相等，往后找；
//  arr2:d e f  \0                     当arr2中'd'与arr1中'c'比较是不相等，往后找
//                                     当arr2中'd'与arr1中'd'比较是相等，则arr2的第二个元素可以向后找；
//                                     当arr2中'e'与arr1中'e'比较是相等，arr2的第三个元素向后找；
//                                     当arr2中'f'与arr1中'f'比较是相等，但是arr2中'\0'表示结束，则不需要匹配；
//                                     因此经过上面一次匹配 arr1，arr2中,匹配到'def'，则打印出来的结果就是'defabcdef'.
//                                                                 
// strstr的作用就是比较两个数组有没有相同的地方，就比如上面两个数组匹配到"def"是相同部分，则arr1取掉"abc"这里，把后面与arr2结合
// 
// 匹配多次:
// arr1:a b b b c d e f  \0    //要设三个变量，s1=arr1,           s2=arr2,               cur=arr1;
//                                                |                 |                      |
//arr2:b b c  \0                             在循环中遍历arr1   在循环中遍历arr2   记录当前可能的匹配开始位置
//                             因为在匹配的时候会出现未知起始位置的情况，因此用cur来记录匹配的起始位置
//                             当arr2中'b'与arr1中'a'不相等，往后找；
//                             当arr2中'b'与arr1中'b'相等，则arr2第二个元素可以往后找；
//                             当arr2中'b'与arr1中'b'相等，arr2第三个元素往后找；
//                             当arr2中'c'与arr1第四个元素b不相等，则arr2返回起始位置，用cur记录arr1返回第二个元素的位置
//                            
//                             当arr2中'b'与arr1第二个元素b相等，arr2第二个元素往后找；
//                             当arr2中'b'与arr1第三个元素b相等，arr2第三个元素往后找；
//                             当arr2中'c'与arr1第四个元素b不相等，则arr2返回起始位置，用cur记录arr1返回第三个元素的位置
// 
//                             当arr2中'b'与arr1第三个元素b相等，arr2第二个元素往后找；
//                             当arr2中'b'与arr1第四个元素b相等，arr2第三个元素往后找；
//                             当arr2中'b'与arr1第五个元素c相等，arr2中'\0'表示结束，则不需要匹配；
// 
//                             经过上面三次匹配得出结果，结果是"bbcdef"


//const char* my_strstr(const char* str1, const char* str2)
//{
//	assert(str1 && str2);
//	const char* s1 = str1;
//	const char* s2 = str2;
//	const char* cur = str1;//cur指针记可能得开始匹配的位置
//
//	if (*str2 == '\0')//当str2是空字符串时，直接返回str1
//		return str1;
//	while (*cur)
//	{
//		//完成一次匹配
//		s1 = cur;
//		s2 = str2;
//		while (*s1&&*s2&&*s1 == *s2)//解释：*s1是确保s1没有指向字符串的末尾
//		{                           //      *s2是确保s2没有指向字符串的末尾
//			s1++;                   //   s1==s2是比较s1和s2当前指向的字符是否相同，如果相同就继续比较下一个字符，不相同就匹配失败
//			s2++;
//		}
//		if (*s2 == '\0')
//			return cur;
//		cur++;
//	}
//	return NULL;
//}
//
//int main()
//{
//	char arr1[] = "abbcdfe";
//	char arr2[] = "bbc";
//	char* ret = my_strstr(arr1, arr2);
//	if (ret == NULL)
//	{
//		printf("找不到\n");
//	}
//	else
//	{
//		printf("找到了:%s\n", ret);
//	}
//	return 0;
//}


//strtok 函数的使用
//比如：
// char arr1[]="www.baidu.com"
// char arr2[]="zpengwei@yeah.net"
// 
// strtok就会把arr1,arr2中的'.' '@'改成'\0'
// arr1 ===>www  \0 
//          baidu \0
//          com    \0
// 
// arr2 ===>zpengwei\0
//          yeah     \0
//          net       \0
//
//
//
//int main()
//{
//	char arr1[] = "zpengwei@yeah.net";
//	char sep[] = "@.";
//	char buf[30] = { 0 };
//	strcpy(buf, arr1);//把arr1传给buf
//
//	char* p = strtok(buf, sep);
//	printf("%s\n", p);//只打印了"zpengwei"
//
//	p = strtok(NULL, sep);
//	printf("%s\n", p);
//
//	p = strtok(NULL, sep);
//	printf("%s\n", p);
//
   // • strtok函数的第一个参数不为 NULL ，函数将找到str中第一个标记，strtok函数将保存它在字符串中的位置。
   //• strtok函数的第一个参数为 NULL ，函数将在同一个字符串中被保存的位置开始，查找下一个标记。
//
// //上面的写法不行，虽然正确但不行   
//	return 0;
//}

//int main()
//{
//	//char arr1[] = "zpengwei@yeah.net";
//	char arr1[] = "192@168#110.123";
//	char sep[] = "@#.";
//	char buf[30] = { 0 };
//	strcpy(buf, arr1);
//
//	char* p = NULL;
//	for (p=strtok(buf,sep);p!=NULL;p=strtok(NULL,sep))
//	{
//		printf("%s\n", p);
//	}
//	return 0;
//}


//strerror 函数的使用
//strerror 函数可以把参数部分错误码对应的错误信息的字符串地址返回来。
//
//int main()
//{
//	int i = 0;
//	for (i = 0; i < 10; i++)
//	{
//		printf("%d:%s\n", i, strerror(i));
//	}
//	return 0;
//}
//
// 完整写法：
#include<errno.h>
//int main()
//{
//	FILE* pf = fopen("test.txt", "r");
//	if (pf == NULL)
//	{
//		printf("文件打开失败，原因是：");
//		printf("%s\n", strerror(errno));//用errno需要头文件#include<errno.h>
//		return 1;//错误返回
//	}
//	//打开成功
//	//....(略)
//
//	//关闭文件
//	fclose(pf);
//	pf = NULL;
//
//	return 0;
//}

//int main()
//{
//	FILE* pf = fopen("test.txt", "r");
//	if (pf == NULL)
//	{
//		//用perror更简便,不用多写
//		perror("文件打开失败，原因是");
//		return 1;//错误返回
//	}
//	//打开成功
//	//....(略)
//
//	//关闭文件
//	fclose(pf);
//	pf = NULL;
//
//	return 0;
//}

